home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’95 / Venus / image.cc < prev    next >
Encoding:
Text File  |  1995-06-23  |  21.2 KB  |  862 lines  |  [TEXT/MSWD]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *         Implementation of the Primitive Operations
  7.  *
  8.  *   The image is represented as a Pixmap, i.e. a matrix of pixels
  9.  *    each of them specifies the gray level at a particular point
  10.  *
  11.  ************************************************************************
  12.  */
  13.  
  14. #pragma implementation "image.h"
  15. #include "std.h"
  16. #include "image.h"
  17.  
  18.  
  19.  
  20. /*
  21.  *------------------------------------------------------------------------
  22.  *            Constructors and destructors
  23.  */
  24.  
  25. void IMAGE::allocate(
  26.     const int no_rows,        // No. of rows
  27.     const int no_cols,        // No. of cols
  28.     const int depth            // No. of bits per pixel
  29. )
  30. {
  31.   valid_code = IMAGE_val_code;
  32.  
  33.   assure((ncols=no_cols) > 0, "Zero image width unexpected");
  34.   assure((nrows=no_rows) > 0, "Zero image height unexpected");
  35.   assure((bits_per_pixel=depth) > 0 && depth <= GRAY_MAXBIT, 
  36.      "Zero or too large no. of bits per pixel");
  37.  
  38.   name    = "";
  39.   npixels = nrows * ncols;
  40.  
  41.   assert( (scanrows = (GRAY **)calloc(nrows,sizeof(GRAY *))) != 0 );
  42.   assert( (pixels   = (GRAY *)calloc(npixels,sizeof(GRAY))) != 0 );
  43.  
  44.   register int i;
  45.   for(i=0; i<nrows; i++)
  46.     scanrows[i] = &pixels[i*ncols];
  47. }
  48.  
  49.                 // Set a new image name
  50. #if 0
  51. void IMAGE::set_name(const char * new_name)
  52. {
  53.   if( name != 0 && name[0] != '\0' )    // Dispose of the previous image name
  54.     delete name;
  55.  
  56.   if( new_name == 0 || new_name[0] == '\0' )
  57.     name = "";                // Image is anonymous now
  58.   else
  59.     name = new char[strlen(new_name)+1], strcpy(name,new_name);
  60. }
  61. #endif
  62.  
  63.                     // Routing constructor module
  64. IMAGE::IMAGE(const IMAGE_CREATORS_1op op, const IMAGE& prototype)
  65. {
  66.   switch(op)
  67.   {
  68.     case Expand:
  69.          _expand(prototype);
  70.      break;
  71.  
  72.     case Shrink:
  73.      _shrink(prototype);
  74.      break;
  75.  
  76.     default:
  77.      _error("Operation %d is not yet implemented",op);
  78.   }
  79. }
  80.  
  81.  
  82. IMAGE::~IMAGE(void)        // Dispose the image struct
  83. {
  84.   is_valid();
  85.   if( name != 0 && name[0] != '\0' )
  86.     delete name;
  87.  
  88.   delete scanrows;
  89.   delete pixels;
  90.   valid_code = 0;
  91. }
  92.  
  93.  
  94. /*
  95.  *------------------------------------------------------------------------
  96.  *             Single Image operations
  97.  */
  98.  
  99.                 // Clip pixel values to
  100.                 // [0,1<<bits_per_pixel-1].
  101.                 // A pixel with the value outside that range
  102.                 // (i.e. negative or too big) is set to
  103.                 // 0 or 1<<bits_per_pixel-1, resp.
  104. IMAGE& IMAGE::clip_to_intensity_range(void)
  105. {
  106.   is_valid();
  107.   const int maxval = (1<<bits_per_pixel)-1;
  108.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  109.   for(; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  110.     if( *cp < 0 )
  111.       *cp = 0;
  112.     else if( *cp > maxval )
  113.       *cp = maxval;
  114.  
  115.   return *this;
  116. }
  117.  
  118.                 // Perform a transformation
  119.                 // pixel = |(signed)pixel|
  120.                 // on all the pixels of the image
  121. IMAGE& IMAGE::abs(void)
  122. {
  123.   is_valid();
  124.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  125.   for(; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  126.     if( *cp < 0 )
  127.       *cp = -(*cp);
  128.  
  129.   return *this;
  130. }
  131.  
  132.                 // Perform a transformation
  133.                 // pixel = fp((signed)pixel)
  134.                 // on all the pixels of the image
  135.                 // where fp is a user-defined function
  136. IMAGE& IMAGE::apply(USER_F * fp)
  137. {
  138.   is_valid();
  139.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  140.   for(; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  141.     *cp = fp(*cp);
  142.  
  143.   return *this;
  144. }
  145.  
  146.                 // Perform the histogram equalization
  147. IMAGE& IMAGE::equalize(const int no_grays)
  148. {
  149. #if 0
  150.   is_valid();
  151.   int orig_no_grays = 1 << bits_per_pixel;
  152.   assert( no_grays <= orig_no_grays );
  153.  
  154.   int histogram [orig_no_grays];
  155.   memset(histogram,0,sizeof(histogram));
  156.  
  157.                 // Evaluate the histogram of an image
  158.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  159.   for(; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  160.   {
  161.     if( *cp <= 0 )
  162.       *cp = 0;
  163.     else if( *cp >= orig_no_grays )
  164.       *cp = orig_no_grays-1;
  165.     histogram[*cp]++;
  166.   }
  167.  
  168.   const int pixels_per_bin_optimal = (npixels + no_grays - 1)/no_grays;
  169.   const int gray_shade_subsample_factor = 
  170.     (orig_no_grays + no_grays -1)/no_grays;
  171.   register int pixel;
  172.   int new_pixel, new_pixel_old;
  173.   int accumulated = 0;
  174.   int optimal_accumulated = pixels_per_bin_optimal;
  175.                     // Mapping from pixels of original
  176.   short look_up_table[orig_no_grays];    // image to [new_pixel_old,new_pixel]
  177.                     // (actually, just to the center of
  178.                     // this interval)
  179.  
  180.                       // Equalizing the histogram
  181.   for(pixel=0,new_pixel=0,new_pixel_old=0; pixel<orig_no_grays; pixel++)
  182.   {
  183.     accumulated += histogram[pixel];
  184.     while( accumulated > optimal_accumulated )
  185.       new_pixel += gray_shade_subsample_factor, 
  186.       optimal_accumulated += pixels_per_bin_optimal;
  187.     assert( new_pixel < orig_no_grays );
  188.     look_up_table[pixel] = (new_pixel > 
  189.                 new_pixel_old+gray_shade_subsample_factor ?
  190.                 (new_pixel + new_pixel_old)/2 :
  191.                 new_pixel);
  192.     new_pixel_old = new_pixel;
  193.   }
  194.  
  195.                 // Update the image according to the LUT
  196.   for(cp = (GRAY_SIGNED *)pixels; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  197.     *cp = look_up_table[*cp];
  198.  
  199. #endif
  200.   return *this;
  201. }
  202.  
  203.                 // Compute the 1. norm of the entire image
  204.                 // SUM{ |(signed)pixel[i,j]| }
  205. double IMAGE::norm_1(void) const
  206. {
  207. #if 0
  208.   is_valid();
  209.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  210.   double sum = 0;
  211.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  212.     sum += ::abs(*cp++);
  213.  
  214.   return sum;
  215. #endif
  216.   return 0;
  217. }
  218.  
  219.                 // Compute the square of the 2. norm of 
  220.                 // the entire image
  221.                 // SUM{ |(signed)pixel[i,j]|^2 }
  222. double IMAGE::norm_2_sqr(void) const
  223. {
  224. #if 0
  225.   is_valid();
  226.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  227.   register double sum = 0;
  228.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  229.     sum += ::sqr((long int)*cp++);
  230.  
  231.   return sum;
  232. #endif
  233.   return 0;
  234. }
  235.  
  236.                 // Compute the infinity norm of the
  237.                 // entire image
  238.                 // MAX{ |(signed)pixel[i,j]| }
  239. int IMAGE::norm_inf(void) const
  240. {
  241. #if 0
  242.   is_valid();
  243.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  244.   register int maxp = 0;
  245.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  246.     maxp = ::max(::abs(*cp++),maxp);
  247.  
  248.   return maxp;
  249. #endif
  250.   return 0;
  251. }
  252.  
  253.                 // Find extremum values of image pixels
  254. Extrema::Extrema(const IMAGE& image)
  255.     : max_pixel(0,0), min_pixel(0,0)
  256. {
  257.   image.is_valid();
  258.   max_value = min_value = image(0,0);
  259.  
  260.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)image.pixels;
  261.   register int i,j;
  262.   for(i=0; i<image.nrows; i++)
  263.     for(j=0; j<image.ncols; j++, cp++)
  264.       if( *cp > max_value )
  265.     max_value = *cp, max_pixel.row_val = i, max_pixel.col_val = j;
  266.       else if( *cp < min_value )
  267.     min_value = *cp, min_pixel.row_val = i, min_pixel.col_val = j;
  268. }
  269.  
  270.                 // Normalize pixel values to be
  271.                 // in range 0..1<<bits_per_pixel-1
  272. IMAGE& IMAGE::normalize_for_display(void)
  273. {
  274.   is_valid();
  275.   Extrema extrema(*this);
  276.   message("\nImage_normalization:"
  277.       "\n\tmin pixel value %d, max pixel value %d",
  278.       extrema.min(), extrema.max());
  279.   if( extrema.max() != extrema.min() )
  280.   {
  281.     double factor = (double)((1<<bits_per_pixel)-1) /
  282.             ( extrema.max() - extrema.min() );
  283.     message("\n\tNormalization is as follows: (pixel - %d)*%g\n",
  284.         extrema.min(), factor);
  285.     register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  286.     for(; cp < (GRAY_SIGNED *)pixels + npixels; cp++)
  287.       *cp = (int)( (*cp - extrema.min()) * factor + 0.5 );
  288.   }
  289.  
  290.   return *this;
  291. }
  292.  
  293.                 // Print some info about the image
  294. void IMAGE::info(void) const
  295. {
  296.   message("\nimage %dx%dx%d '%s' ",nrows,ncols,bits_per_pixel,name);
  297. }
  298.                 // Print the image as a table of pixel values
  299.                 // (zeros are printed as dots)
  300. void IMAGE::print(const char * title) const
  301. {
  302.   is_valid();
  303.   message("\nImage %dx%dx%d '%s' is as follows\n\n",nrows,ncols,
  304.       bits_per_pixel,title);
  305.  
  306.   register int i,j;
  307.   for(i=0; i<nrows; i++)
  308.   {
  309.     for(j=0; j<ncols; j++)
  310.       if( (*this)(i,j) == 0 )
  311.     message("   . ");
  312.       else
  313.     message("%4d ",(*this)(i,j));
  314.     message("\n");
  315.   }
  316.   message("Done\n");
  317. }
  318.  
  319. /*
  320.  *------------------------------------------------------------------------
  321.  *             Image-scalar operations
  322.  *       Check to see if the preedicate "(signed)pixel operation scalar"
  323.  *        holds for ALL the pixels of the image
  324.  */
  325.  
  326.                 // (signed)pixel == val for all pixels?
  327. int IMAGE::operator == (const int val) const
  328. {
  329.   is_valid();
  330.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  331.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  332.     if( !(*cp++ == val) )
  333.       return 0;
  334.  
  335.   return 1;
  336. }
  337.  
  338.                 // (signed)pixel != val for all pixels?
  339. int IMAGE::operator != (const int val) const
  340. {
  341.   is_valid();
  342.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  343.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  344.     if( !(*cp++ != val) )
  345.       return 0;
  346.  
  347.   return 1;
  348. }
  349.  
  350.                 // (signed)pixel <  val for all pixels?
  351. int IMAGE::operator < (const int val) const
  352. {
  353.   is_valid();
  354.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  355.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  356.     if( !(*cp++ < val) )
  357.       return 0;
  358.  
  359.   return 1;
  360. }
  361.  
  362.                 // (signed)pixel <= val for all pixels?
  363. int IMAGE::operator <= (const int val) const
  364. {
  365.   is_valid();
  366.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  367.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  368.     if( !(*cp++ <= val) )
  369.       return 0;
  370.  
  371.   return 1;
  372. }
  373.  
  374.                 // (signed)pixel > val for all pixels?
  375. int IMAGE::operator > (const int val) const
  376. {
  377.   is_valid();
  378.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  379.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  380.     if( !(*cp++ > val) )
  381.       return 0;
  382.  
  383.   return 1;
  384. }
  385.  
  386.                 // (signed)pixel >= val for all pixels?
  387. int IMAGE::operator >= (const int val) const
  388. {
  389.   is_valid();
  390.   register GRAY_SIGNED * cp = (GRAY_SIGNED *)pixels;
  391.   for(; cp < (GRAY_SIGNED *)pixels + npixels; )
  392.     if( !(*cp++ >= val) )
  393.       return 0;
  394.  
  395.   return 1;
  396. }
  397.  
  398. /*
  399.  *------------------------------------------------------------------------
  400.  *             Image-scalar operations
  401.  *          Modify every pixel according to the operation
  402.  */
  403.  
  404.                 // Assign a value to all the pixels
  405. IMAGE& IMAGE::operator = (const int val)
  406. {
  407.   is_valid();
  408.   register GRAY * cp = pixels;
  409.   while( cp < pixels+npixels )
  410.     *cp++ = val;
  411.  
  412.   return *this;
  413. }
  414.  
  415.                 // Add to all pixels
  416. IMAGE& IMAGE::operator += (const int val)
  417. {
  418.   is_valid();
  419.   register GRAY * cp = pixels;
  420.   while( cp < pixels+npixels )
  421.     *cp++ += val;
  422.  
  423.   return *this;
  424. }
  425.  
  426.                 // Subtract a value from all the pixels
  427. IMAGE& IMAGE::operator -= (const int val)
  428. {
  429.   is_valid();
  430.   register GRAY * cp = pixels;
  431.   while( cp < pixels+npixels )
  432.     *cp++ -= val;
  433.  
  434.   return *this;
  435. }
  436.  
  437.                 // Multiply a value by all the pixels
  438. IMAGE& IMAGE::operator *= (const int val)
  439. {
  440.   is_valid();
  441.   register GRAY * cp = pixels;
  442.   while( cp < pixels+npixels )
  443.     *cp++ *= val;
  444.  
  445.   return *this;
  446. }
  447.  
  448.                 // Logical OR a value by all the pixels
  449. IMAGE& IMAGE::operator |= (const int val)
  450. {
  451.   is_valid();
  452.   register GRAY * cp = pixels;
  453.   while( cp < pixels+npixels )
  454.     *cp++ |= val;
  455.  
  456.   return *this;
  457. }
  458.  
  459.                 // Logical AND a value by all the pixels
  460. IMAGE& IMAGE::operator &= (const int val)
  461. {
  462.   is_valid();
  463.   register GRAY * cp = pixels;
  464.   while( cp < pixels+npixels )
  465.     *cp++ &= val;
  466.  
  467.   return *this;
  468. }
  469.  
  470.                 // Logical XOR a value by all the pixels
  471. IMAGE& IMAGE::operator ^= (const int val)
  472. {
  473.   is_valid();
  474.   register GRAY * cp = pixels;
  475.   while( cp < pixels+npixels )
  476.     *cp++ ^= val;
  477.  
  478.   return *this;
  479. }
  480.  
  481. #if 0
  482.                 // Shift the value of all the pixels
  483. IMAGE& IMAGE::operator <<= (const int val)
  484. {
  485.   is_valid();
  486.   if( ::abs(val) >= GRAY_MAXBIT )
  487.     _error("Very fishy shift factor: %d",val);
  488.  
  489.   register GRAY * cp = pixels;
  490.   while( cp < pixels+npixels )
  491.     *cp++ <<= val;
  492.  
  493.   return *this;
  494. }
  495.  
  496.                 // Shift the value of all the pixels
  497. IMAGE& IMAGE::operator >>= (const int val)
  498. {
  499.   is_valid();
  500.   if( abs(val) >= GRAY_MAXBIT )
  501.     _error("Very fishy shift factor: %d",val);
  502.  
  503.   register GRAY * cp = pixels;
  504.   while( cp < pixels+npixels )
  505.     *cp++ >>= val;
  506.  
  507.   return *this;
  508. }
  509. #endif
  510.  
  511. /*
  512.  *------------------------------------------------------------------------
  513.  *             Image-Image operations
  514.  *          Modify the target image according to the operation
  515.  */
  516.  
  517. IMAGE& IMAGE::operator = (const IMAGE& source)
  518. {
  519.   are_compatible(*this,source);
  520.   memcpy(pixels,source.pixels,npixels*sizeof(GRAY));
  521.   return *this;
  522. }
  523.  
  524. int identical(const IMAGE& im1, const IMAGE& im2)
  525. {
  526.   are_compatible(im1,im2);
  527.   return (memcmp(im1.pixels,im2.pixels,im1.npixels*sizeof(GRAY)) == 0);
  528. }
  529.  
  530.                 // Add the source to the target
  531. IMAGE& operator += (IMAGE& target, const IMAGE& source)
  532. {
  533.   are_compatible(target,source);
  534.  
  535.   register GRAY * sp = source.pixels;
  536.   register GRAY * tp = target.pixels;
  537.   while( tp < target.pixels + target.npixels )
  538.     *tp++ += *sp++;
  539.   
  540.   return target;
  541. }
  542.   
  543.                 // Subtract the source from the target
  544. IMAGE& operator -= (IMAGE& target, const IMAGE& source)
  545. {
  546.   are_compatible(target,source);
  547.  
  548.   register GRAY * sp = source.pixels;
  549.   register GRAY * tp = target.pixels;
  550.   while( tp < target.pixels + target.npixels )
  551.     *tp++ -= *sp++;
  552.   
  553.   return target;
  554. }
  555.  
  556.                 // Modified addition
  557.                 //    Target += scalar*Source
  558. IMAGE& add(IMAGE& target, const int scalar,const IMAGE& source)
  559. {
  560.   are_compatible(target,source);
  561.  
  562.   register GRAY * sp = source.pixels;
  563.   register GRAY * tp = target.pixels;
  564.   while( tp < target.pixels + target.npixels )
  565.     *tp++ += scalar * *sp++;
  566.   
  567.   return target;
  568. }
  569.  
  570. #if 0
  571.                 // Shift the source to 'pos', clip it 
  572.                 // if necessary, multiply by the scalar,
  573.                 // and add
  574. IMAGE& IMAGE::shift_clip_add(rowcol pos, const int scalar, const IMAGE& source)
  575. {
  576.   source.is_valid();
  577.   is_valid();
  578.  
  579.                     // Find an intersection of 'source'
  580.                     // shifted to 'pos' (relative to
  581.                     // the image) with the (target) image
  582.                     // Only this rectangle will be 
  583.                     // affected by addition
  584.   rowcol s_orig(max(0,-pos.row()),max(0,-pos.col()));
  585.   rowcol t_orig(max(0,pos.row()),max(0,pos.col()));
  586.                     // No. of rows in the intersection
  587.   const int irows = min(nrows - t_orig.row(),source.nrows - s_orig.row());
  588.                     // No. of cols in the intersection
  589.   const int icols = min(ncols - t_orig.col(),source.ncols - s_orig.col());
  590.   if( irows <= 0 || icols <= 0 )
  591.     source.info(),
  592.     info(),
  593.     _error("The first image shifted by (%d,%d) does not intersect the other",
  594.        pos.row(),pos.col());
  595.  
  596.                     // See the explanation in the class
  597.                     // Rectangle
  598.   const int s_inc_to_nextrow = source.ncols - icols;    
  599.   const int t_inc_to_nextrow = ncols - icols;    
  600.  
  601.   register GRAY_SIGNED * sp = 
  602.     (GRAY_SIGNED *)&(source.scanrows[s_orig.row()])[s_orig.col()];
  603.   register GRAY_SIGNED * tp = 
  604.     (GRAY_SIGNED *)&(scanrows[t_orig.row()])[t_orig.col()];
  605.  
  606.   register int i,j;
  607.   for(i=0; i<irows; i++, sp += s_inc_to_nextrow, tp += t_inc_to_nextrow)
  608.     for(j=0; j<icols; j++)
  609.       *tp++ += scalar * *sp++;
  610.  
  611.   return *this;
  612. }
  613. #endif
  614.  
  615.                 // Evaluate the scalar product of two images
  616. double operator * (const IMAGE& im1, const IMAGE& im2)
  617. {
  618.   are_compatible(im1,im2);
  619.  
  620.   register GRAY_SIGNED * p1 = (GRAY_SIGNED *)im1.pixels;
  621.   register GRAY_SIGNED * p2 = (GRAY_SIGNED *)im2.pixels;
  622.   register double sum = 0;
  623.  
  624.   while( p1 < (GRAY_SIGNED *)im1.pixels + im1.npixels )
  625.     sum += *p1++ * *p2++;
  626.  
  627.   return sum;
  628. }
  629.  
  630. #if 0
  631.             // Estimate the norm of the difference 
  632.             // between two (signed) image
  633.                 // SUM{ |(signed)pixel[i,j]| }
  634. double norm_1(const IMAGE& im1, const IMAGE& im2)
  635. {
  636.   are_compatible(im1,im2);
  637.  
  638.   register GRAY_SIGNED * p1 = (GRAY_SIGNED *)im1.pixels;
  639.   register GRAY_SIGNED * p2 = (GRAY_SIGNED *)im2.pixels;
  640.   register long long sum = 0;
  641.  
  642.   while( p1 < (GRAY_SIGNED *)im1.pixels + im1.npixels )
  643.     sum += ::abs(*p1++ - *p2++);
  644.  
  645.   return sum;
  646. }
  647.  
  648.                 // SUM{ |(signed)pixel[i,j]|^2 }
  649. double norm_2_sqr(const IMAGE& im1, const IMAGE& im2)
  650. {
  651.   are_compatible(im1,im2);
  652.  
  653.   register GRAY_SIGNED * p1 = (GRAY_SIGNED *)im1.pixels;
  654.   register GRAY_SIGNED * p2 = (GRAY_SIGNED *)im2.pixels;
  655.   register double sum = 0;
  656.  
  657.   while( p1 < (GRAY_SIGNED *)im1.pixels + im1.npixels )
  658.     sum += ::sqr((long int)(*p1++ - *p2++));
  659.  
  660.   return sum;
  661. }
  662.                 // MAX{ |(signed)pixel[i,j]| }
  663. int norm_inf(const IMAGE& im1, const IMAGE& im2)
  664. {
  665.   are_compatible(im1,im2);
  666.  
  667.   register GRAY_SIGNED * p1 = (GRAY_SIGNED *)im1.pixels;
  668.   register GRAY_SIGNED * p2 = (GRAY_SIGNED *)im2.pixels;
  669.   register int maxp = 0;
  670.  
  671.   while( p1 < (GRAY_SIGNED *)im1.pixels + im1.npixels )
  672.     maxp = max(maxp,::abs(*p1++ - *p2++));
  673.  
  674.   return maxp;
  675. }
  676. #endif
  677.  
  678.                 // OR the source to the target
  679. IMAGE& operator |= (IMAGE& target, const IMAGE& source)
  680. {
  681.   are_compatible(target,source);
  682.  
  683.   register GRAY * sp = source.pixels;
  684.   register GRAY * tp = target.pixels;
  685.   while( tp < target.pixels + target.npixels )
  686.     *tp++ |= *sp++;
  687.   
  688.   return target;
  689. }
  690.  
  691.                 // AND the source to the target
  692. IMAGE& operator &= (IMAGE& target, const IMAGE& source)
  693. {
  694.   are_compatible(target,source);
  695.  
  696.   register GRAY * sp = source.pixels;
  697.   register GRAY * tp = target.pixels;
  698.   while( tp < target.pixels + target.npixels )
  699.     *tp++ &= *sp++;
  700.   
  701.   return target;
  702. }
  703.  
  704.                 // XOR the source to the target
  705. IMAGE& operator ^= (IMAGE& target, const IMAGE& source)
  706. {
  707.   are_compatible(target,source);
  708.  
  709.   register GRAY * sp = source.pixels;
  710.   register GRAY * tp = target.pixels;
  711.   while( tp < target.pixels + target.npixels )
  712.     *tp++ ^= *sp++;
  713.   
  714.   return target;
  715. }
  716.  
  717. #if 0
  718. #include <builtin.h>
  719. void compare(            // Compare the two images
  720.     const IMAGE& image1,    // and print out the result of comparison
  721.     const IMAGE& image2,
  722.     const char * title )
  723. {
  724.   register int i,j;
  725.  
  726.   are_compatible(image1,image2);
  727.  
  728.   message("\n\nComparison of two images %dx%dx%d\n%s\n",image1.nrows,
  729.      image1.ncols,image1.bits_per_pixel,title);
  730.  
  731.   if( image1.bits_per_pixel != image2.bits_per_pixel )
  732.     message("\nNote, images have different depth, %d and %d\n",
  733.          image1.bits_per_pixel, image2.bits_per_pixel);
  734.  
  735.   double int norm1 = 0, norm2 = 0;    // Norm of the images
  736.   double int ndiff = 0;        // Norm of the difference
  737.   int imax=0,jmax=0,difmax = -1;    // For the pixels that differ most
  738.                     // Image scanline pointer
  739.   register GRAY_SIGNED *rowp1 = (GRAY_SIGNED *)image1.pixels;
  740.   register GRAY_SIGNED *rowp2 = (GRAY_SIGNED *)image2.pixels;
  741.  
  742.   int im1_neg_pixel = 0;        // Flags whether negative pixels
  743.   int im2_neg_pixel = 0;        // were encountered
  744.  
  745.   for(i=0; i < image1.nrows; i++)
  746.     for(j=0; j < image1.ncols; j++)
  747.     {
  748.       int pv1 = *rowp1++;
  749.       int pv2 = *rowp2++;
  750.       int diff = abs(pv1-pv2);
  751.  
  752.       if( pv1 < 0 )
  753.     im1_neg_pixel = 1, pv1 = -pv1;
  754.       if( pv2 < 0 )
  755.     im2_neg_pixel = 1, pv2 = -pv2;
  756.  
  757.       if( diff > difmax )
  758.       {
  759.     difmax = diff;
  760.     imax = i;
  761.     jmax = j;
  762.       }
  763.       norm1 += pv1;
  764.       norm2 += pv2;
  765.       ndiff += diff;
  766.     }
  767.  
  768.   if( im1_neg_pixel )
  769.     message("\n*** Warning: a pixel with negative value has been encountered "
  770.         "in image 1\n");
  771.   if( im2_neg_pixel )
  772.     message("\n*** Warning: a pixel with negative value has been encountered "
  773.         "in image 2\n");
  774.  
  775.   message("\nMaximal discrepancy    \t\t%d",difmax);
  776.   message("\n   occured at the pixel\t\t(%d,%d)",imax,jmax);
  777.   const int pv1 = image1(imax,jmax);
  778.   const int pv2 = image2(imax,jmax);
  779.   message("\n Image 1 pixel is    \t\t%d",pv1);
  780.   message("\n Image 2 pixel is    \t\t%d",pv2);
  781.   message("\n Absolute error v2[i]-v1[i]\t\t%d",pv2-pv1);
  782.   message("\n Relative error\t\t\t\t%g\n",
  783.      (pv2-pv1)/max((float)abs(pv2+pv1)/2,1e-7) );
  784.  
  785.   message("\nL1 norm of image 1 per pixel \t\t%g",
  786.                       (double)norm1/image1.npixels);
  787.   message("\nL1 norm of image 2 per pixel \t\t%g",
  788.                     (double)norm2/image2.npixels);
  789.   message("\nL1 norm of image1-image2 per pixel\t\t\t%g",
  790.                     (double)ndiff/image1.npixels);
  791.   message("\n||Image1-Image2||/sqrt(||Image1|| ||Image2||)\t%g\n\n",
  792.       ndiff/max( sqrt(norm1*norm2), 1e-7 )         );
  793.  
  794. }
  795. #endif
  796.  
  797. /*
  798.  *------------------------------------------------------------------------
  799.  *                Expansion/Shrinking of the image
  800.  */
  801.  
  802.                 // Expand the prototype twice in each
  803.                 // dimension
  804.                 // In other words, blow each pixel of the
  805.                 // prototype to the 2x2 square
  806. void IMAGE::_expand(const IMAGE& prototype)
  807. {
  808.   prototype.is_valid();
  809.   allocate(2*prototype.nrows,2*prototype.ncols,prototype.bits_per_pixel);
  810.  
  811.   register GRAY * tp = pixels;
  812.   register GRAY * pp = prototype.pixels;
  813.   register int i,j;
  814.  
  815.   for(i=0; i<prototype.nrows; i++, tp+=ncols)
  816.     for(j=0; j<prototype.ncols; j++)
  817.     {
  818.       register int pixel = *pp++;
  819.       *(tp+ncols) = pixel;        // Fill out 2x2 square of the
  820.       *tp++       = pixel;        // blown image with a pixel value
  821.       *(tp+ncols) = pixel;
  822.       *tp++       = pixel;
  823.     }
  824.  
  825.   assert( pp == prototype.pixels + prototype.npixels );
  826.   assert( tp == pixels + npixels );
  827. }
  828.  
  829.                 // Shrink the prototype twice in each
  830.                 // dimension. The image row and column
  831.                 // dimensions are assumed to be even numbers
  832.                 // Image is shrunk by replacing 2x2 square
  833.                 // by one pixel with an average intensity
  834.                 // over the square
  835. void IMAGE::_shrink(const IMAGE& prototype)
  836. {
  837.   prototype.is_valid();
  838.   if( (prototype.nrows & 1) || (prototype.ncols & 1) )
  839.     _error("No of rows and columns in the image to shrink should both be even",
  840.        (prototype.info(),0));
  841.   allocate(prototype.nrows/2,prototype.ncols/2,prototype.bits_per_pixel);
  842.  
  843.   register GRAY * tp = pixels;
  844.   register GRAY * pp = prototype.pixels;
  845.   register int i,j;
  846.  
  847.   for(i=0; i<nrows; i++)
  848.   {                    // Average row-by-row
  849.     for(j=0; j<ncols; j++)
  850.       *tp = *pp++, *tp++ += *pp++;    // Sum of pairs of the prototype pixels
  851.     tp -= ncols;
  852.     for(j=0; j<ncols; j++, tp++, pp+=2)
  853.     {
  854.       register int av = *tp + pp[0] + pp[1];    // This is the aver of 4 pixels
  855.       *tp = ( av & 2 ? (av >> 2) + 1 : av >> 2 );    // /4 with rounding
  856.     }
  857.   }
  858.   assert( pp == prototype.pixels + prototype.npixels );
  859.   assert( tp == pixels + npixels );
  860. }
  861.  
  862.